Izpētiet Heksagonālo un Tīro arhitektūru, lai veidotu uzturējamas, mērogojamas un testējamas frontend lietojumprogrammas. Apgūstiet to principus, priekšrocības un praktiskās ieviešanas stratēģijas.
Frontend arhitektūra: Heksagonālā un Tīrā arhitektūra mērogojamām lietojumprogrammām
Pieaugot frontend lietojumprogrammu sarežģītībai, labi definēta arhitektūra kļūst izšķiroša uzturējamībai, testējamībai un mērogojamībai. Divi populāri arhitektūras modeļi, kas risina šīs problēmas, ir Heksagonālā arhitektūra (zināma arī kā Porti un Adapteri) un Tīrā arhitektūra. Lai gan šie principi radušies backend pasaulē, tos var efektīvi pielietot frontend izstrādē, lai radītu robustas un pielāgojamas lietotāja saskarnes.
Kas ir Frontend arhitektūra?
Frontend arhitektūra nosaka dažādu komponentu struktūru, organizāciju un mijiedarbību frontend lietojumprogrammā. Tā nodrošina plānu, kā lietojumprogramma tiek veidota, uzturēta un mērogota. Laba frontend arhitektūra veicina:
- Uzturējamība: Vieglāk saprast, modificēt un atkļūdot kodu.
- Testējamība: Atvieglo vienībtestu un integrācijas testu rakstīšanu.
- Mērogojamība: Ļauj lietojumprogrammai tikt galā ar pieaugošu sarežģītību un lietotāju slodzi.
- Atkārtota izmantojamība: Veicina koda atkārtotu izmantošanu dažādās lietojumprogrammas daļās.
- Elastīgums: Pielāgojas mainīgām prasībām un jaunām tehnoloģijām.
Bez skaidras arhitektūras frontend projekti var ātri kļūt monolīti un grūti pārvaldāmi, kas noved pie paaugstinātām izstrādes izmaksām un samazinātas veiklības.
Ievads Heksagonālajā arhitektūrā
Heksagonālā arhitektūra, ko ierosināja Alisters Kokberns (Alistair Cockburn), mērķis ir atsaistīt lietojumprogrammas biznesa loģikas kodolu no ārējām atkarībām, piemēram, datubāzēm, UI ietvariem un trešo pušu API. To panāk, izmantojot Portu un Adapteru koncepciju.
Heksagonālās arhitektūras galvenie jēdzieni:
- Kodols (Domēns): Satur lietojumprogrammas biznesa loģiku un lietošanas gadījumus. Tas ir neatkarīgs no jebkādiem ārējiem ietvariem vai tehnoloģijām.
- Porti: Saskarnes, kas definē, kā kodols mijiedarbojas ar ārpasauli. Tie pārstāv kodola ievades un izvades robežas.
- Adapteri: Portu implementācijas, kas savieno kodolu ar konkrētām ārējām sistēmām. Ir divu veidu adapteri:
- Vadošie adapteri (Primārie adapteri): Uzsāk mijiedarbību ar kodolu. Piemēri ietver UI komponentus, komandrindas saskarnes vai citas lietojumprogrammas.
- Vadītie adapteri (Sekundārie adapteri): Tiek izsaukti no kodola, lai mijiedarbotos ar ārējām sistēmām. Piemēri ietver datubāzes, API vai failu sistēmas.
Kodols neko nezina par konkrētajiem adapteriem. Tas mijiedarbojas ar tiem tikai caur portiem. Šī atsaiste ļauj viegli nomainīt dažādus adapterus, neietekmējot kodola loģiku. Piemēram, jūs varat pārslēgties no viena UI ietvara (piemēram, React) uz citu (piemēram, Vue.js), vienkārši nomainot vadošo adapteri.
Heksagonālās arhitektūras priekšrocības:
- Uzlabota testējamība: Biznesa loģikas kodolu var viegli testēt izolēti, nepaļaujoties uz ārējām atkarībām. Jūs varat izmantot viltus adapterus (mock adapters), lai simulētu ārējo sistēmu darbību.
- Palielināta uzturējamība: Izmaiņām ārējās sistēmās ir minimāla ietekme uz kodola loģiku. Tas atvieglo lietojumprogrammas uzturēšanu un attīstīšanu laika gaitā.
- Lielāks elastīgums: Jūs varat viegli pielāgot lietojumprogrammu jaunām tehnoloģijām un prasībām, pievienojot vai nomainot adapterus.
- Uzlabota atkārtota izmantojamība: Biznesa loģikas kodolu var atkārtoti izmantot dažādos kontekstos, savienojot to ar dažādiem adapteriem.
Ievads Tīrajā arhitektūrā
Tīrā arhitektūra, ko popularizējis Roberts C. Mārtins (Uncle Bob), ir vēl viens arhitektūras modelis, kas uzsver rūpju nodalīšanu (separation of concerns) un atsaisti. Tā koncentrējas uz tādas sistēmas izveidi, kas ir neatkarīga no ietvariem, datubāzēm, UI un jebkuras ārējas aģentūras.
Tīrās arhitektūras galvenie jēdzieni:
Tīrā arhitektūra organizē lietojumprogrammu koncentriskos slāņos, kur centrā ir visabstraktākais un atkārtoti izmantojamākais kods, bet ārējos slāņos - viskonkrētākais un tehnoloģijai specifiskākais kods.
- Entītijas (Entities): Pārstāv lietojumprogrammas galvenos biznesa objektus un noteikumus. Tās ir neatkarīgas no jebkurām ārējām sistēmām.
- Lietošanas gadījumi (Use Cases): Definē lietojumprogrammas biznesa loģiku un to, kā lietotāji mijiedarbojas ar sistēmu. Tie orķestrē entītijas, lai veiktu konkrētus uzdevumus.
- Saskarnes adapteri (Interface Adapters): Pārveido datus starp lietošanas gadījumiem un ārējām sistēmām. Šis slānis ietver prezentētājus (presenters), kontrolierus (controllers) un vārtejas (gateways).
- Ietvari un draiveri (Frameworks and Drivers): Ārējais slānis, kas satur UI ietvaru, datubāzi un citas ārējās tehnoloģijas.
Atkarību noteikums Tīrajā arhitektūrā nosaka, ka ārējie slāņi var būt atkarīgi no iekšējiem slāņiem, bet iekšējie slāņi nevar būt atkarīgi no ārējiem slāņiem. Tas nodrošina, ka biznesa loģikas kodols ir neatkarīgs no jebkādiem ārējiem ietvariem vai tehnoloģijām.
Tīrās arhitektūras priekšrocības:
- Neatkarīga no ietvariem: Arhitektūra nepaļaujas uz kādas funkcijām bagātas programmatūras bibliotēkas esamību. Tas ļauj jums izmantot ietvarus kā rīkus, nevis būt spiestiem ievietot savu sistēmu to ierobežotajos rāmjos.
- Testējama: Biznesa noteikumus var testēt bez UI, datubāzes, tīmekļa servera vai jebkura cita ārēja elementa.
- Neatkarīga no UI: UI var viegli mainīt, nemainot pārējo sistēmu. Tīmekļa UI var aizstāt ar konsoles UI, nemainot nevienu no biznesa noteikumiem.
- Neatkarīga no datubāzes: Jūs varat nomainīt Oracle vai SQL Server pret Mongo, BigTable, CouchDB vai ko citu. Jūsu biznesa noteikumi nav saistīti ar datubāzi.
- Neatkarīga no jebkuras ārējas aģentūras: Patiesībā jūsu biznesa noteikumi vienkārši neko nezina par ārpasauli.
Heksagonālās un Tīrās arhitektūras pielietošana Frontend izstrādē
Lai gan Heksagonālā un Tīrā arhitektūra bieži tiek saistītas ar backend izstrādi, to principus var efektīvi pielietot frontend lietojumprogrammām, lai uzlabotu to arhitektūru un uzturējamību. Lūk, kā:
1. Identificējiet kodolu (Domēnu)
Pirmais solis ir identificēt jūsu frontend lietojumprogrammas biznesa loģikas kodolu. Tas ietver entītijas, lietošanas gadījumus un biznesa noteikumus, kas ir neatkarīgi no UI ietvara vai jebkādiem ārējiem API. Piemēram, e-komercijas lietojumprogrammā kodols varētu ietvert loģiku produktu, iepirkumu grozu un pasūtījumu pārvaldībai.
Piemērs: Uzdevumu pārvaldības lietojumprogrammā kodola domēns varētu sastāvēt no:
- Entītijas: Uzdevums, Projekts, Lietotājs
- Lietošanas gadījumi: IzveidotUzdevumu, AtjauninātUzdevumu, PiešķirtUzdevumu, PabeigtUzdevumu, UzdevumuSaraksts
- Biznesa noteikumi: Uzdevumam jābūt nosaukumam, uzdevumu nevar piešķirt lietotājam, kurš nav projekta dalībnieks.
2. Definējiet Portus un Adapterus (Heksagonālā arhitektūra) vai Slāņus (Tīrā arhitektūra)
Tālāk definējiet portus un adapterus (Heksagonālā arhitektūra) vai slāņus (Tīrā arhitektūra), kas atdala kodolu no ārējām sistēmām. Frontend lietojumprogrammā tie varētu būt:
- UI komponenti (Vadošie adapteri/Ietvari un draiveri): React, Vue.js, Angular komponenti, kas mijiedarbojas ar lietotāju.
- API klienti (Vadītie adapteri/Saskarnes adapteri): Pakalpojumi, kas veic pieprasījumus uz backend API.
- Datu krātuves (Vadītie adapteri/Saskarnes adapteri): Vietējā krātuve (Local storage), IndexedDB vai citi datu glabāšanas mehānismi.
- Stāvokļa pārvaldība (Saskarnes adapteri): Redux, Vuex vai citas stāvokļa pārvaldības bibliotēkas.
Piemērs, izmantojot Heksagonālo arhitektūru:
- Kodols: Uzdevumu pārvaldības loģika (entītijas, lietošanas gadījumi, biznesa noteikumi).
- Porti:
TaskService(definē metodes uzdevumu izveidei, atjaunināšanai un iegūšanai). - Vadošais adapteris: React komponenti, kas izmanto
TaskService, lai mijiedarbotos ar kodolu. - Vadītais adapteris: API klients, kas implementē
TaskServiceun veic pieprasījumus uz backend API.
Piemērs, izmantojot Tīro arhitektūru:
- Entītijas: Uzdevums, Projekts, Lietotājs (tīri JavaScript objekti).
- Lietošanas gadījumi: CreateTaskUseCase, UpdateTaskUseCase (orķestrē entītijas).
- Saskarnes adapteri:
- Kontrolieri: Apstrādā lietotāja ievadi no UI.
- Prezentētāji: Formatē datus attēlošanai UI.
- Vārtejas: Mijiedarbojas ar API klientu.
- Ietvari un draiveri: React komponenti, API klients (axios, fetch).
3. Implementējiet Adapterus (Heksagonālā arhitektūra) vai Slāņus (Tīrā arhitektūra)
Tagad implementējiet adapterus vai slāņus, kas savieno kodolu ar ārējām sistēmām. Pārliecinieties, ka adapteri vai slāņi ir neatkarīgi no kodola un ka kodols mijiedarbojas ar tiem tikai caur portiem vai saskarnēm. Tas ļauj viegli nomainīt dažādus adapterus vai slāņus, neietekmējot kodola loģiku.
Piemērs (Heksagonālā arhitektūra):
// TaskService Port
interface TaskService {
createTask(taskData: TaskData): Promise;
updateTask(taskId: string, taskData: TaskData): Promise;
getTask(taskId: string): Promise;
}
// API Client Adapter
class ApiTaskService implements TaskService {
async createTask(taskData: TaskData): Promise {
// Make API request to create a task
}
async updateTask(taskId: string, taskData: TaskData): Promise {
// Make API request to update a task
}
async getTask(taskId: string): Promise {
// Make API request to get a task
}
}
// React Component Adapter
function TaskList() {
const taskService: TaskService = new ApiTaskService();
const handleCreateTask = async (taskData: TaskData) => {
await taskService.createTask(taskData);
// Update the task list
};
// ...
}
Piemērs (Tīrā arhitektūra):
// Entities
class Task {
constructor(public id: string, public title: string, public description: string) {}
}
// Use Case
class CreateTaskUseCase {
constructor(private taskGateway: TaskGateway) {}
async execute(title: string, description: string): Promise {
const task = new Task(generateId(), title, description);
await this.taskGateway.create(task);
return task;
}
}
// Interface Adapters - Gateway
interface TaskGateway {
create(task: Task): Promise;
}
class ApiTaskGateway implements TaskGateway {
async create(task: Task): Promise {
// Make API request to create task
}
}
// Interface Adapters - Controller
class TaskController {
constructor(private createTaskUseCase: CreateTaskUseCase) {}
async createTask(req: Request, res: Response) {
const { title, description } = req.body;
const task = await this.createTaskUseCase.execute(title, description);
res.json(task);
}
}
// Frameworks & Drivers - React Component
function TaskForm() {
const [title, setTitle] = useState('');
const [description, setDescription] = useState('');
const apiTaskGateway = new ApiTaskGateway();
const createTaskUseCase = new CreateTaskUseCase(apiTaskGateway);
const taskController = new TaskController(createTaskUseCase);
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
await taskController.createTask({ body: { title, description } } as Request, { json: (data: any) => console.log(data) } as Response);
};
return (
);
}
4. Implementējiet Atkarību injekciju (Dependency Injection)
Lai vēl vairāk atsaistītu kodolu no ārējām sistēmām, izmantojiet atkarību injekciju, lai nodrošinātu adapterus vai slāņus kodolam. Tas ļauj viegli nomainīt dažādas adapteru vai slāņu implementācijas, nemainot kodola kodu.
Piemērs:
// Inject the TaskService into the TaskList component
function TaskList(props: { taskService: TaskService }) {
const { taskService } = props;
const handleCreateTask = async (taskData: TaskData) => {
await taskService.createTask(taskData);
// Update the task list
};
// ...
}
// Usage
const apiTaskService = new ApiTaskService();
5. Rakstiet Vienībtestus
Viena no galvenajām Heksagonālās un Tīrās arhitektūras priekšrocībām ir uzlabota testējamība. Jūs varat viegli rakstīt vienībtestus biznesa loģikas kodolam, nepaļaujoties uz ārējām atkarībām. Izmantojiet viltus adapterus vai slāņus, lai simulētu ārējo sistēmu darbību un pārbaudītu, vai kodola loģika darbojas kā paredzēts.
Piemērs:
// Mock TaskService
class MockTaskService implements TaskService {
async createTask(taskData: TaskData): Promise {
return Promise.resolve({ id: '1', ...taskData });
}
async updateTask(taskId: string, taskData: TaskData): Promise {
return Promise.resolve({ id: taskId, ...taskData });
}
async getTask(taskId: string): Promise {
return Promise.resolve({ id: taskId, title: 'Test Task', description: 'Test Description' });
}
}
// Unit Test
describe('TaskList', () => {
it('should create a task', async () => {
const mockTaskService = new MockTaskService();
const taskList = new TaskList({ taskService: mockTaskService });
const taskData = { title: 'New Task', description: 'New Description' };
const newTask = await taskList.handleCreateTask(taskData);
expect(newTask.title).toBe('New Task');
expect(newTask.description).toBe('New Description');
});
});
Praktiski apsvērumi un izaicinājumi
Lai gan Heksagonālā un Tīrā arhitektūra piedāvā būtiskas priekšrocības, ir arī daži praktiski apsvērumi un izaicinājumi, kas jāpatur prātā, tos pielietojot frontend izstrādē:
- Paaugstināta sarežģītība: Šīs arhitektūras var pievienot koda bāzei sarežģītību, īpaši mazām vai vienkāršām lietojumprogrammām.
- Mācīšanās līkne: Izstrādātājiem var būt nepieciešams apgūt jaunus jēdzienus un modeļus, lai efektīvi ieviestu šīs arhitektūras.
- Pārmērīga inženierija: Ir svarīgi izvairīties no lietojumprogrammas pārmērīgas inženierijas. Sāciet ar vienkāršu arhitektūru un pakāpeniski pievienojiet sarežģītību pēc nepieciešamības.
- Abstrakcijas līdzsvarošana: Atbilstoša abstrakcijas līmeņa atrašana var būt izaicinājums. Pārāk daudz abstrakcijas var padarīt kodu grūti saprotamu, savukārt pārāk maz abstrakcijas var novest pie ciešas saites.
- Veiktspējas apsvērumi: Pārmērīgi abstrakcijas slāņi var potenciāli ietekmēt veiktspēju. Ir svarīgi profilēt lietojumprogrammu un identificēt jebkādus veiktspējas vājos punktus.
Starptautiski piemēri un adaptācijas
Heksagonālās un Tīrās arhitektūras principi ir piemērojami frontend izstrādē neatkarīgi no ģeogrāfiskās atrašanās vietas vai kultūras konteksta. Tomēr konkrētās implementācijas un adaptācijas var atšķirties atkarībā no projekta prasībām un izstrādes komandas vēlmēm.
1. piemērs: Globāla e-komercijas platforma
Globāla e-komercijas platforma varētu izmantot Heksagonālo arhitektūru, lai atsaistītu iepirkumu groza un pasūtījumu pārvaldības loģikas kodolu no UI ietvara un maksājumu vārtejām. Kodols būtu atbildīgs par produktu pārvaldību, cenu aprēķināšanu un pasūtījumu apstrādi. Vadošie adapteri ietvertu React komponentus produktu katalogam, iepirkumu grozam un norēķinu lapām. Vadītie adapteri ietvertu API klientus dažādām maksājumu vārtejām (piemēram, Stripe, PayPal, Alipay) un piegādes pakalpojumu sniedzējiem (piemēram, FedEx, DHL, UPS). Tas ļauj platformai viegli pielāgoties dažādām reģionālām maksājumu metodēm un piegādes iespējām.
2. piemērs: Daudzvalodu sociālo mediju lietojumprogramma
Daudzvalodu sociālo mediju lietojumprogramma varētu izmantot Tīro arhitektūru, lai atdalītu lietotāju autentifikācijas un satura pārvaldības loģikas kodolu no UI un lokalizācijas ietvariem. Entītijas pārstāvētu lietotājus, ierakstus un komentārus. Lietošanas gadījumi definētu, kā lietotāji veido, kopīgo un mijiedarbojas ar saturu. Saskarnes adapteri apstrādātu satura tulkošanu dažādās valodās un datu formatēšanu dažādiem UI komponentiem. Tas ļauj lietojumprogrammai viegli atbalstīt jaunas valodas un pielāgoties dažādām kultūras vēlmēm.
Noslēgums
Heksagonālā un Tīrā arhitektūra sniedz vērtīgus principus uzturējamu, testējamu un mērogojamu frontend lietojumprogrammu veidošanai. Atsaistot biznesa loģikas kodolu no ārējām atkarībām, jūs varat izveidot elastīgāku un pielāgojamāku koda bāzi, kuru ir vieglāk attīstīt laika gaitā. Lai gan šīs arhitektūras sākotnēji var pievienot zināmu sarežģītību, ilgtermiņa ieguvumi uzturējamības, testējamības un mērogojamības ziņā padara tās par vērtīgu ieguldījumu sarežģītos frontend projektos. Atcerieties sākt ar vienkāršu arhitektūru un pakāpeniski pievienot sarežģītību pēc nepieciešamības, kā arī rūpīgi apsvērt praktiskos apsvērumus un izaicinājumus.
Pieņemot šos arhitektūras modeļus, frontend izstrādātāji var veidot robustākas un uzticamākas lietojumprogrammas, kas spēj apmierināt mainīgās lietotāju vajadzības visā pasaulē.
Papildu literatūra
- Hexagonal Architecture: https://alistaircockburn.com/hexagonal-architecture/
- Clean Architecture: https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html